package model;

import model.interfaces.DicePair;
import model.interfaces.GameEngine;
import model.interfaces.GameEngineCallback;
import model.interfaces.Player;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * Created by heyuxun on 2018/4/4.
 */
public class GameEngineImpl implements GameEngine{
    ArrayList<Player> players= new ArrayList<>();// To store players
    ArrayList<GameEngineCallback> GameEngineCallbacks= new ArrayList<>();//Arraylist to store callback engine
    DicePair Dices =new DicePairImpl(0,0,NUM_FACES);// Dice initializing
    GameEngineCallback gameEngineCallback=  new GameEngineCallbackImpl();// callback engine initializing
    int houseResult=0;//To store house dices result
    @Override
    public boolean placeBet(Player player, int bet) {
        if (player.getPoints()>= bet)
        {
            if (player.placeBet(bet))
            player.setPoints(player.getPoints()-bet);//deduct bet to start a new gamble
            return true;
        }
        else
          return false;
    }

    @Override
    public void rollPlayer(Player player, int initialDelay, int finalDelay, int delayIncrement) {
        for (int i=initialDelay;i<finalDelay;i=i+delayIncrement){//To judge the time of loop, by using time delay
            player.setRollResult(Dices);// set a random value for Dices
            gameEngineCallback.intermediateResult(player,Dices,null);//using callback engine to logging
            if (i> finalDelay-delayIncrement) {// last time of loop, settle result
                gameEngineCallback.result(player, Dices, null);
            }

        }
    }

    @Override
    public void rollHouse(int initialDelay, int finalDelay, int delayIncrement) {
        for (int i=initialDelay;i<finalDelay;i=i+delayIncrement){//same as rollPlayer
            Dices.getDice1();//set a random dice value of one side
            Dices.getDice2();//set a random dice value of another side
            gameEngineCallback.intermediateHouseResult(Dices, null);
            if (i> finalDelay-delayIncrement)//result step
            {
                Dices.getDice1();
                Dices.getDice2();
                gameEngineCallback.houseResult(Dices,null);
                houseResult= Dices.getNumFaces();// To get house result
            }
        }
        for (int i=0;i<players.size();i++){
            if (players.get(i).getRollResult()>houseResult)// final bets judge, win or lose
            players.get(i).setPoints(players.get(i).getPoints()+2*players.get(i).getBet());// win, 2 times of bet
            if (players.get(i).getRollResult()==houseResult)// final bets judge, equal
                players.get(i).setPoints(players.get(i).getPoints()+players.get(i).getBet());// equal, return bet
            gameEngineCallback.playerResult(players.get(i),null);
        }
    }

    @Override
    public void addPlayer(Player player) {
        players.add(player);// To add new player
    }

    @Override
    public Player getPlayer(String id) {
        for (int i=0;i<players.size();i++)// To find the id in exist players
            if (players.get(i).getPlayerId()== id)
                return players.get(i);// Id exist, return the player
        return null;// Id not exist, return null
    }

    @Override
    public boolean removePlayer(Player player) {
        for (int i=0;i<players.size();i++)// To find the player in exist players
            if (players.get(i) == player) {
                players.remove(i);//player exist, removing
                return true;
            }
        return false;//player not exist, return false
    }

    @Override
    public void addGameEngineCallback(GameEngineCallback gameEngineCallback) {
        GameEngineCallbacks.add(gameEngineCallback);// Add new GameEngineCallback
    }

    @Override
    public boolean removeGameEngineCallback(GameEngineCallback gameEngineCallback) {
        for (int i=0;i< GameEngineCallbacks.size();i++)// To find the gameEngineCallback in exist list
            if (GameEngineCallbacks.get(i)== gameEngineCallback) {
                GameEngineCallbacks.remove(i);//gameEngineCallback exist, removing
                return true;
            }
        return false;//gameEngineCallback not exist, return false
    }

    @Override
    public Collection<Player> getAllPlayers() {
        List <Player> unmodifyplayers = Collections.unmodifiableList(players);//get an unmodified List of players
        return unmodifyplayers;
    }


}
